/**
* @file lcd_if_fsmc_mcu8.c
* @brief  lcd interface for FSMC mcu 8bit
* @details 
* @author huangbin
* @version V1.0.0
* @date 2025-04-20
* @copyright All documents are copyrighted by Shenzhen Xinlongwei Technology Co., LTD.
*            They may not be used for commercial purposes without permission
*/
/*
lcd的fsmc mcu8接口抽象文件，所有上层不同驱动ic共享此接口文件。
接口类型：8bit mcu 8080
*/
#include "inc.h"
#include	"lcd_if_fsmc_mcu8.h"



static void fsmc_mcu8_gpio_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd ( FSMC_MCU8_CS_CLK|FSMC_MCU8_DC_CLK | FSMC_MCU8_WR_CLK|FSMC_MCU8_RD_CLK	| FSMC_MCU8_BK_CLK|FSMC_MCU8_RST_CLK
                            | FSMC_MCU8_D0_CLK | FSMC_MCU8_D1_CLK |	FSMC_MCU8_D2_CLK | FSMC_MCU8_D3_CLK 
                            | FSMC_MCU8_D4_CLK | FSMC_MCU8_D5_CLK | FSMC_MCU8_D6_CLK | FSMC_MCU8_D7_CLK, ENABLE );
		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF_PP;

	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_D0_PIN;
	GPIO_Init ( FSMC_MCU8_D0_PORT, & GPIO_InitStructure );

	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_D1_PIN;
	GPIO_Init ( FSMC_MCU8_D1_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_D2_PIN;
	GPIO_Init ( FSMC_MCU8_D2_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_D3_PIN;
	GPIO_Init ( FSMC_MCU8_D3_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_D4_PIN;
	GPIO_Init ( FSMC_MCU8_D4_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_D5_PIN;
	GPIO_Init ( FSMC_MCU8_D5_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_D6_PIN;
	GPIO_Init ( FSMC_MCU8_D6_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_D7_PIN;
	GPIO_Init ( FSMC_MCU8_D7_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF_PP;
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_RD_PIN; 
	GPIO_Init (FSMC_MCU8_RD_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_WR_PIN; 
	GPIO_Init (FSMC_MCU8_WR_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_CS_PIN; 
	GPIO_Init ( FSMC_MCU8_CS_PORT, & GPIO_InitStructure );  
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_DC_PIN; 
	GPIO_Init ( FSMC_MCU8_DC_PORT, & GPIO_InitStructure );
	

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_RST_PIN; 
	GPIO_Init ( FSMC_MCU8_RST_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
	GPIO_InitStructure.GPIO_Pin = FSMC_MCU8_BK_PIN; 
	GPIO_Init ( FSMC_MCU8_BK_PORT, & GPIO_InitStructure );
    
	FSMC_MCU8_BK_OFF();
    FSMC_MCU8_RESET_HIGH();
	DebugPrintf("LCD1 init mcu8080 io!\r\n");	
}
static void fsmc_mcu8_config( void )
{
	FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
	FSMC_NORSRAMTimingInitTypeDef  readWriteTiming; 	
	
	/*enable clock*/
	RCC_AHBPeriphClockCmd (RCC_AHBPeriph_FSMC, ENABLE );
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_LCD_AF3,ENABLE);

	//地址建立时间,3个 clock
	readWriteTiming.FSMC_AddressSetupTime      = 0x03;
	//数据保持时间	
	readWriteTiming.FSMC_DataSetupTime         = 0x04;
	
	//模式B,异步NOR FLASH模式，与lcd的8080时序匹配
	readWriteTiming.FSMC_AccessMode            = FSMC_AccessMode_B;	
	
    /*以下配置与模式B无关*/
	//地址保持时间（ADDHLD）模式A未用到
	readWriteTiming.FSMC_AddressHoldTime       = 0x00;
	//设置总线转换周期，仅用于复用模式的NOR操作
	readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
	//设置时钟分频，仅用于同步类型的存储器
	readWriteTiming.FSMC_CLKDivision           = 0x00;
	//数据保持时间，仅用于同步型的NOR
	readWriteTiming.FSMC_DataLatency           = 0x00;	

	FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait      = FSMC_AsynchronousWait_Disable;
	FSMC_NORSRAMInitStructure.FSMC_Bank                  = FSMC_Bank_NORSRAMx;
	FSMC_NORSRAMInitStructure.FSMC_DataAddressMux        = FSMC_DataAddressMux_Disable;
	FSMC_NORSRAMInitStructure.FSMC_MemoryType            = FSMC_MemoryType_NOR;
	FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth       = FSMC_MemoryDataWidth_8b;
	FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode       = FSMC_BurstAccessMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity    = FSMC_WaitSignalPolarity_Low;
	FSMC_NORSRAMInitStructure.FSMC_WrapMode              = FSMC_WrapMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive      = FSMC_WaitSignalActive_BeforeWaitState;
	FSMC_NORSRAMInitStructure.FSMC_WriteOperation        = FSMC_WriteOperation_Enable;
	FSMC_NORSRAMInitStructure.FSMC_WaitSignal            = FSMC_WaitSignal_Disable;
	FSMC_NORSRAMInitStructure.FSMC_ExtendedMode          = FSMC_ExtendedMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WriteBurst            = FSMC_WriteBurst_Disable;
	FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;
	FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct     = &readWriteTiming;
	
	FSMC_NORSRAMInit ( & FSMC_NORSRAMInitStructure ); 

	FSMC_NORSRAMCmd ( FSMC_Bank_NORSRAMx, ENABLE );  	
}
///////////////////////////////lcd命令接口///////////////////////////////////////////////
static void fsmc_mcu8_reset ( void )
{			
	FSMC_MCU8_RESET_HIGH();		 	 
	FSMC_MCU8_RESET_LOW();
	LCD_Delay(100); 					   
	FSMC_MCU8_RESET_HIGH();		 	 
	LCD_Delay(10); 	
}
//背光控制
void fsmc_mcu8_BackLightSet(uint8_t duty)
{
    if(LCD_BACKLIGHT_ON == duty)
        FSMC_MCU8_BK_ON();
    else if(LCD_BACKLIGHT_OFF == duty)
        FSMC_MCU8_BK_OFF();
//    else
//        //setpwm(duty);
}
static void fsmc_mcu8_write_reg ( uint8_t reg )
{
	* ( __IO uint8_t * ) ( FSMC_ADDR_CMD ) = reg;
}
static void fsmc_mcu8_write_data ( uint8_t data )
{
	* ( __IO uint8_t * ) ( FSMC_ADDR_DATA ) = data;
}
static uint8_t fsmc_mcu8_read_data (void)
{
	return * ( __IO uint8_t * ) ( FSMC_ADDR_DATA );
}
///////////////////////////////////////////////////////////////////////////////////////
//写寄存器及数据(一条完整的命令)
static void fsmc_mcu8_WriteCommand(uint8_t LCD_Reg, uint8_t *pRegValue,uint8_t len)
{
	uint32_t i;

	fsmc_mcu8_write_reg(LCD_Reg);

	for(i = 0; i < len; i++)
	{
		uint8_t dat = *pRegValue;
		fsmc_mcu8_write_data(dat);
		pRegValue++;
	}
}
static uint16_t LcdXOffset,LcdYOffset;

static void fsmc_mcu8_setwindow (uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1)
{	
	__ALIGNED(4) uint8_t buffer[4];

	x0 += LcdXOffset;
	x1 += LcdXOffset;
	y0 += LcdYOffset;
	y1 += LcdYOffset;
	
	buffer[0] = (uint8_t)(x0 >> 8);
	buffer[1] = (uint8_t)(x0);
	buffer[2] = (uint8_t)((x1 - 1) >> 8);
	buffer[3] = (uint8_t)(x1 - 1);
	fsmc_mcu8_WriteCommand(0x2a,buffer,4);

	buffer[0] = (uint8_t)(y0 >> 8);
	buffer[1] = (uint8_t)(y0);
	buffer[2] = (uint8_t)((y1 - 1) >> 8);
	buffer[3] = (uint8_t)(y1 - 1);
	fsmc_mcu8_WriteCommand(0x2b,buffer,4);
	
	fsmc_mcu8_write_reg(0x2c);
}
//休眠进入和唤醒
void fsmc_mcu8_SleepInOut(bool sleep)
{
//	if(sleep) //sleep in
//	{
//	}
//	else //sleep out
//	{
//	}
}
//写同一个颜色的显示数据
static void fsmc_mcu8_WriteColor16(HCOLOR color,uint32_t len)
{
	uint8_t h,l;
	HCOLOR d;

#if GUI_COLOR_DEPTH == GUI_COLOR_24BIT
	d = ((((uint16_t)(GET_COLOR_R(color) >> 3)) << 11) | (((uint16_t)(GET_COLOR_G(color) >> 2)) << 5) | ((uint16_t)(GET_COLOR_B(color) >> 3)));
#elif GUI_COLOR_DEPTH == GUI_COLOR_16BIT 
    d = color;
#endif    
	h = (uint8_t)((d >> 8) & 0xFF);	
	l = (uint8_t)(d  & 0xFF);
	while(len--)
	{
		fsmc_mcu8_write_data(h);		//先写高8bit
		fsmc_mcu8_write_data(l);		//再写低8bit
	}	
}
//写显示数据
static void fsmc_mcu8_WriteData16(HCOLOR *psrc,uint32_t len)
{
	uint32_t u8Len = len;
	
	while(u8Len--)
	{
		uint8_t h,l;
		uint16_t d;
		HCOLOR color;
		
		color = *psrc++;
#if GUI_COLOR_DEPTH == GUI_COLOR_24BIT
		d = ((((uint16_t)(GET_COLOR_R(color) >> 3)) << 11) | (((uint16_t)(GET_COLOR_G(color) >> 2)) << 5) | ((uint16_t)(GET_COLOR_B(color) >> 3)));
#elif GUI_COLOR_DEPTH == GUI_COLOR_16BIT 
        d = color;
#endif        

		h = (uint8_t)((d >> 8) & 0xFF);	
		fsmc_mcu8_write_data(h);		//先写高8bit
		l = (uint8_t)(d  & 0xFF);
		fsmc_mcu8_write_data(l);		//再写低8bit
	}
}

//读寄存器数据
//regIndex: 寄存器索引
//pRegData: 保存返回数据
//regNum: 要读的数据字节数
static void fsmc_Mcu8_ReadReg(uint8_t regIndex,uint8_t *pRegData,uint8_t regNum)
{
	fsmc_mcu8_write_reg(regIndex);
	
	for(uint32_t i = 0; i < regNum;i++)
		pRegData[i] = fsmc_mcu8_read_data();
}
void Lcd_RegInterface_FsmcMcu8_16(DRVLCD *pLcd,uint16_t xOffset,uint16_t yOffset)
{
	fsmc_mcu8_gpio_init();
    fsmc_mcu8_config();
	pLcd->SetWindow		= fsmc_mcu8_setwindow;
	pLcd->SleepInOut 	= fsmc_mcu8_SleepInOut;
	pLcd->WriteColor	= fsmc_mcu8_WriteColor16;
	pLcd->WriteData		= fsmc_mcu8_WriteData16;
	pLcd->Reset			= fsmc_mcu8_reset;
	pLcd->BkSet			= fsmc_mcu8_BackLightSet;
	pLcd->WriteIndexReg	= fsmc_mcu8_write_reg;
	pLcd->WriteRegParameter	    = fsmc_mcu8_write_data;
	pLcd->WriteRegAndParameter = fsmc_mcu8_WriteCommand;
	pLcd->ReadReg			= fsmc_Mcu8_ReadReg;
	LcdXOffset = xOffset;
	LcdYOffset = yOffset;
}
/************************END OF FILE*************************************/


